var gamejs = require('gamejs');

/*
 * NEMICI: un oggetto Animation [cicler� tra normale, colpito, esploso] caratterizzato da:
 * - Percorso, un array di punti che individuano, passo passo il percorso da seguire
 * - Velocit�, un intero che dice il numero di pixel passati in un frame
 * - Vita, un intero che rappresenta la vita rimasta
 * - Alpha, un intero [0,100] che dice se e quanto il nemico Ã¨ visibile a occhio nudo di notte
 * - Danno, un intero che dice il numero di vite tolte al pianeta, se questo nemico ci arriva
 * - visibilityTime , tempo che il nemico rimane visibile dopo il ping
 * - detected , un intero che indica se il nemico e` stato rilevato dal radar e quindi e` visibile alle armi
 * - Valore, un intero che ci dice quanto prendiamo uccidendo questo nemico.
 */

/**
 * Creates an enemy
 *
 * @extends Sprite
 * @constructor
 */
var Enemy = exports.Enemy = function(match, startRect) {
	Enemy.superConstructor.apply(this, arguments);
	this.path = [];
	this.pathIndex = 0;
	this.maxSpeed = 0;
	this.speed = 0;
	this.slownessDuration;
	this.started = 0;
	this.health = 0;
	this.fullHealth = 0;
	this.armor = 0;
	this.fullArmor = 0;
	this.alpha = 0;
	this.damage = 0;
	this.visibilityTime = 0;//1000ms
	this.damagePerSecond = 0;
	this.durationDamagePerSecond = 0;
	this.detected = 0;
	this.prize = 0;
	this.scoreForKill = 10;
	this.currentMatch = match;
	this.explosion = gamejs.image.load("resources/images/explosion.png");
	this.explosionTime = 100;
	this.curExplosionTime = 0;
	this.originalImage = gamejs.image.load("resources/images/enemy.png");
	this.detectedImage = gamejs.image.load("resources/images/enemy_detected.png");
	
	this.originalImage = gamejs.transform.scale(
			this.originalImage,
			[this.originalImage.getSize()[0] * (0.5), this.originalImage.getSize()[1] *  (0.5)]
	);
	this.detectedImage = gamejs.transform.scale(
			this.detectedImage,
			[this.detectedImage.getSize()[0] * (0.5), this.detectedImage.getSize()[1] *  (0.5)]
	);
	this.explosion = gamejs.transform.scale(
			this.explosion,
			[this.originalImage.getSize()[0] , this.originalImage.getSize()[1]]
	);
	this.rotation = 0;
	this.image = this.originalImage;
	this.rect = new gamejs.Rect(startRect,this.image.getSize());
	this.curId = Math.random()*1000;
	this.currentMatch.getMap().getPath(this.curId,startRect,[1,200]);
}

/**
 * Return the match where this radar work.
 *
 * @param {Match} The match where this radar work.
 */
Enemy.prototype.getMatch = function() {
	if(this.currentMatch == null)
		throw new ReferenceError("Match not defined");
	return this.currentMatch;
}

/**
 * Trigger a path calculation
 *
 */
Enemy.prototype.pathCalculation = function() {
	if(this.currentMatch == null)
		throw new ReferenceError("Match not defined");
	return this.currentMatch;
}

/**
 * Extending Sprite with Enemy
 */
gamejs.utils.objects.extend(Enemy, gamejs.sprite.Sprite);

/**
 * Return current rect
 * 
 * @return {int, int}
 */
Enemy.getRect = function(){
	if(this.rect == null)
		throw new ReferenceError("Rect not defined");
	return this.rect;
}

/**
 * Return enemy coordinates
 * 
 * @return {int, int}
 */
Enemy.prototype.getCoordinates = function() {
	if(this.rect == null)
		throw new ReferenceError("Rect not defined");
    return this.rect.center;
};

/**
 * Kill enemy with explosion
 * 
 */
Enemy.prototype.killExplosion = function() {
	this.image = this.explosion;
	this.image.setAlpha(this.curExplosionTime/this.explosionTime);
	this.curExplosionTime++;	
	if(this.explosionTime <= this.curExplosionTime){
		this.kill();	
	}
};

/**
 * Updates the position of the Enemy
 * 
 * @param {int} ms duration
 */
Enemy.prototype.update = function(msDuration) {
	if(this.started){
		if(this.health<=0){
			if(this.curExplosionTime==0){
				this.currentMatch.changeScore(this.scoreForKill);
				this.currentMatch.changeCredit(this.prize);
				this.currentMatch.getSoundManager().playExplosion(1);
			}
			this.killExplosion();
			return;
		}
		if (this.durationDamagePerSecond > 0){
			this.health -= (msDuration / 1000) * this.damagePerSecond;
			this.durationDamagePerSecond -= (msDuration / 1000);
		}else{
			this.damagePerSecond = 0;
		}
		if (this.slownessDuration > 0){
			this.slownessDuration -= (msDuration / 1000);
		}else{
			this.speed = this.maxSpeed;
		}
		
		if (this.detected>0){
			this.image = this.detectedImage;
			this.image.setAlpha(0);
		}
		else{
			this.image = this.originalImage;
			this.image.setAlpha(this.alpha);
		}
		
		this.pathIndex += this.speed * (msDuration / 1000);
		var intIndex = Math.round(this.pathIndex);
		if (intIndex >= this.path.length - 1){
			this.kill();
			this.currentMatch.getSoundManager().playExplosion(0);
			this.currentMatch.decreaseHealth(this.damage);
			return;
		}
		//if(this.rect[0][1]!=this.path[intIndex][1] && this.rect[0][0]!=this.path[intIndex][0])
		//if (intIndex < this.path.length - 20)
		//	this.rotation =  Math.atan2(-this.rect.topleft[1]+this.path[intIndex+20][1],-this.rect.topleft[0]+this.path[intIndex+20][0])* 180 / Math.PI;
		//else
		this.rotation = 0;
		this.image = gamejs.transform.rotate(this.image, this.rotation)
		this.rect = new gamejs.Rect([this.path[intIndex][0]-this.image.getSize()[0]/2,this.path[intIndex][1]-this.image.getSize()[1]/2], this.image.getSize());
		if(this.detected > 0)
			this.detected -= msDuration;
	}else{
		var curThis = this;
		var curId = this.curId;
		gamejs.event.get().forEach(function handler(event){
			 if (event.type == gamejs.event.WORKER_RESULT) {
				 if(event.data.wid == curId){
					 if(1){
						 curThis.started=1;
						 curThis.path = event.data.wpath;
					 }
				 }
			 }else{
					gamejs.event.post({
		                type: event.type,
		                data: event.data
		             })
				}
		});
	}
}

/**
 * Subtracts health points
 *
 * @param {int} hitRate The amount of health to subtract
 */
Enemy.prototype.hit = function(hitRate) {
	//if(this.health <= 0)
		//throw new ReferenceError("Cannot decrease life to a killed enemy not defined");
	if(this.armor<=0){
		this.armor = 0;
		this.health -= hitRate;
	}
	else
		this.armor -= hitRate;
}

/**
 * Slow enemy by percentage
 *
 * @param {int} hitRate The percentage of slowness
 */
Enemy.prototype.slow = function(hitRate,duration) {
	this.speed = this.maxSpeed * hitRate;
	this.slownessDuration = duration;
}

/**
 * Give damage per second to enemy 
 *
 * @param {int} hitRate The damage per second
 * @param {int} duration The duration of the effect
 */
Enemy.prototype.dps = function(hitRate,duration) {
	this.damagePerSecond = hitRate;
	this.durationDamagePerSecond = duration;
}

/**
 * Set detected flag to 1, it performs also a timer of visibility
 *
 * @param {boolean} detected True to turn detected mode on, false to turn it off
 */
Enemy.prototype.setDetected = function(detected) {
	if (detected) {
		this.detected = this.visibilityTime;
	}
	else {
		this.detected = 0;
	}
};

/**
 * Return detected flag
 *
 * @return {boolean} true if detected > 0
 */
Enemy.prototype.isDetected = function() {
	return (this.detected > 0) && this.health>0;
}

/**
 * Draw the enemy on the screen
 *
 * @return {gamejs.surface} a valid gamejs surface
 */
Enemy.prototype.draw = function(surface) {
	surface.blit( this.image, this.rect.topleft);
	if(this.isDetected() && this.health>0) {
		gamejs.draw.arc(surface,  "rgb("+Math.round(255 * ( this.fullHealth - this.health) / this.fullHealth)+", "+Math.round(255 * this.health / this.fullHealth)+", 0)",  this.rect, 0, Math.round(360 * this.health / this.fullHealth),2);
		gamejs.draw.arc(surface,  "rgb(0,0,255)",  this.rect, 0, Math.round(360 * this.armor / this.fullArmor),3);
	}
};

